package top.xunfong;

import cn.hutool.captcha.generator.CodeGenerator;
import top.xunfong.domain.ColumnInfo;
import top.xunfong.domain.TableInfo;
import top.xunfong.util.GenerationUtil;

import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.*;
import java.util.*;
import java.util.List;

/**
 * @author: xunfong
 * @date: 2025/10/17 7:58
 */
public class Generation {
    private static final String BASE_URL = "jdbc:mysql://1.15.216.35:3306/test_util?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "ytkr3/spEM;g";

    private static final String API_MODEL_STR = "API_MODULE";

    private static final String SERVICE_MODULE_STR = "SERVICE_MODULE";

    private static final String PACKAGE_NAME_STR = "PACKAGE_NAME";

    // 输出路径
    private static final String OUTPUT_PATH = "/src/main/java/";

    // mapper 输出路径
    private static final String MAPPER_OUTPUT_PATH = "/src/main/resources/mapper/";

    private static final String WEB_OUTPUT_API = "vue-ui/src/api";


    // 模块名， 使用此模块名可以覆盖配置参数覆盖可变参数
    private static final String MODULE_NAME = "knowledge";

    // 可变参数开始 ----------------------------------------------------------------------------------------------------
    // api模块
    private static String API_MODULE = "api/system-api";
    // service 模块
    private static String SERVICE_MODULE = "modules/system";
    // 包名
    private static String PACKAGE_NAME = "top.xunfong.system";
    private static final String[] TABLE_NAMES = new String[]{
            "knowledge_info"
    };
    // 可变参数结束 ----------------------------------------------------------------------------------------------------


    public static void main(String[] args) throws Exception {
        getModules();
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_31);
        cfg.setClassForTemplateLoading(CodeGenerator.class, "/ftl");
        cfg.setDefaultEncoding("UTF-8");
        for (String tableName : TABLE_NAMES) {
            List<TableInfo> tables = GenerationUtil.getTables(BASE_URL, USERNAME, PASSWORD, tableName);
            for (TableInfo table : tables) {
                generateCode(table, cfg);
            }
        }
    }

    public static void generateCode(TableInfo table, Configuration cfg) throws Exception {
        Map<String, Object> data = new HashMap<>();
        data.put("packageName", PACKAGE_NAME);
        data.put("moduleName", MODULE_NAME);
        data.put("tableName", table.getTableName());
        data.put("className", table.getClassName());
        data.put("variableName", table.getVariableName());
        data.put("tableRemarks", table.getRemarks());
        data.put("columns", table.getColumns());
        data.put("dto", table.getClassName() + "DTO");
        data.put("queryDTO", table.getClassName() + "QueryDTO");
        data.put("vo", table.getClassName() + "VO");
        data.put("service", table.getClassName() + "Service");
        data.put("impl", table.getClassName() + "ServiceImpl");
        data.put("controller", table.getClassName() + "Controller");
        data.put("mapper", table.getClassName() + "Mapper");


        // 收集需要导入的包
        Set<String> imports = new HashSet<>();
        for (ColumnInfo column : table.getColumns()) {
            String javaType = column.getJavaType();
            if (javaType.equals("Date")) {
                imports.add("java.util.Date");
            } else if (javaType.equals("BigDecimal")) {
                imports.add("java.math.BigDecimal");
            }
        }
        data.put("imports", imports);

        backEnd(cfg, table, data);
        webPage(cfg, table, data);
    }

    /**
     * 后端相关文件生成
     *
     * @param cfg
     * @param table
     * @param data
     * @throws Exception
     */
    private static void backEnd(Configuration cfg, TableInfo table, Map<String, Object> data) throws Exception {
        // 生成实体类
        generateFile(cfg, "entity.ftl",
                API_MODULE + OUTPUT_PATH + PACKAGE_NAME.replace('.', '/') + "/entity/" + table.getClassName() + ".java",
                data);

        // 生成Service
        generateFile(cfg, "service.ftl",
                SERVICE_MODULE + OUTPUT_PATH + PACKAGE_NAME.replace('.', '/') + "/service/" + data.get("service") + ".java",
                data);

        // 生成ServiceImpl
        generateFile(cfg, "serviceImpl.ftl",
                SERVICE_MODULE + OUTPUT_PATH + PACKAGE_NAME.replace('.', '/') + "/service/impl/" + data.get("impl") + ".java",
                data);

        // 生成Controller
        generateFile(cfg, "controller.ftl",
                SERVICE_MODULE + OUTPUT_PATH + PACKAGE_NAME.replace('.', '/') + "/controller/" + data.get("controller") + ".java",
                data);

        // 生成Mapper
        generateFile(cfg, "mapper.ftl",
                SERVICE_MODULE + OUTPUT_PATH + PACKAGE_NAME.replace('.', '/') + "/mapper/" + data.get("mapper") + ".java",
                data
        );

        // 生成Mapper.xml
        generateFile(cfg, "mapperxml.ftl",
                SERVICE_MODULE + MAPPER_OUTPUT_PATH + table.getClassName() + "Mapper.xml",
                data
        );

        // 生成DTO
        generateFile(cfg, "dto.ftl",
                API_MODULE + OUTPUT_PATH + PACKAGE_NAME.replace('.', '/') + "/dto/" + data.get("dto") + ".java",
                data
        );
        // 生成VO
        generateFile(cfg, "vo.ftl",
                API_MODULE + OUTPUT_PATH + PACKAGE_NAME.replace('.', '/') + "/vo/" + data.get("vo") + ".java",
                data
        );
        // 生成queryDTO
        generateFile(cfg, "query.ftl",
                API_MODULE + OUTPUT_PATH + PACKAGE_NAME.replace('.', '/') + "/dto/" + data.get("queryDTO") + ".java",
                data
        );
    }

    /**
     * 前端页面生成
     */
    private static void webPage(Configuration cfg, TableInfo table, Map<String, Object> data) throws Exception {
        // 生成api
        generateFile(cfg, "web/api.ftl",
                WEB_OUTPUT_API + "/" + MODULE_NAME + "/" + data.get("variableName") + ".js",
                data
        );
    }

    private static void generateFile(Configuration cfg, String templateName,
                                     String outputPath, Map<String, Object> data) throws Exception {
        Template template = cfg.getTemplate(templateName);
        File file = new File(outputPath);
        file.getParentFile().mkdirs();

        try (Writer out = new FileWriter(file)) {
            template.process(data, out);
        }
    }

    /**
     * 构建模块默认参数
     *
     * @return
     */
    private static void getModules() {
        Map<String, Map<String, String>> modules = new HashMap<>();
        // system模块
        Map<String, String> system = new HashMap<>();
        system.put(API_MODEL_STR, "api/system-api");
        system.put(SERVICE_MODULE_STR, "modules/system");
        system.put(PACKAGE_NAME_STR, "top.xunfong.system");
        modules.put("system", system);
        // knowledge模块
        Map<String, String> knowledge = new HashMap<>();
        knowledge.put(API_MODEL_STR, "api/knowledge-api");
        knowledge.put(SERVICE_MODULE_STR, "modules/knowledge");
        knowledge.put(PACKAGE_NAME_STR, "top.xunfong.knowledge");
        modules.put("knowledge", knowledge);
        if (modules.containsKey(MODULE_NAME)) {
            Map<String, String> module = modules.get(MODULE_NAME);
            API_MODULE = module.get(API_MODEL_STR);
            SERVICE_MODULE = module.get(SERVICE_MODULE_STR);
            PACKAGE_NAME = module.get(PACKAGE_NAME_STR);
        }
    }
}
